home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / CSUBR.LZH / FEXPND.C < prev    next >
C/C++ Source or Header  |  1985-11-17  |  8KB  |  310 lines

  1. /*******************************************************/
  2.  
  3. /*
  4.     fexpnd returns a pointer to the next filename.ext which
  5.     matches the first parameter (str) or a zero is no file 
  6.     matches that parameter.  The given parameter is processed 
  7.     to generate a normalized search string and a normalized 
  8.     path prefix.  The prefix is returned in the area pointed to 
  9.     by the second parameter.  This string may be concatenated 
  10.     with the returned value to give a fully-qualified dataset 
  11.     name for open, rename, erase, etc.
  12.  
  13.     You should continue calling fexpnd with the same first 
  14.     parameter until it returns a zero, then pass it a new first 
  15.     parameter.  This can be used to expand a list of ambiguous 
  16.     filenames on a parameter list.   */
  17.  
  18.  
  19. char mydta[80] = {0};
  20. char fxs[80] = {0};
  21. char fxsrch[80] = {0};
  22. char fxpref[80] = {0};
  23.  
  24. char *fexpnd(str, path)
  25. char *str, *path;
  26. {
  27.     int getret, fixpath(), strcpy(), dirnxt(), dirfst();
  28.     int savdta(), restdta();
  29.     char *rindex();
  30.  
  31.     savdta();        /* save old dta in an unknown location */
  32.     setdta(&mydta); /* make MS-DOS use my dta */
  33.     if (strcmp(str,fxs) == 0)
  34.         getret = dirnxt();        /* MS-DOS 2.0+ get next function */
  35.     else {
  36.         strcpy(fxs,str);            /* for detection of a new name */
  37.         if (!fixpath(str, fxsrch, fxpref))
  38.             return (0);
  39.         strcpy(path, fxpref);        /* give path to caller */
  40.         getret = dirfst(fxsrch);    /* MS-DOS 2.0+ get first function */
  41.     }
  42.  
  43.     restdta();        /* restore old dta */
  44.     if (getret == 0)  {
  45.         return(&mydta[30]);        /* return filename.ext  */
  46.     }
  47.     else
  48.         return 0;
  49. }
  50.  
  51. int dtads, dtadx;
  52.  
  53. savdta()
  54. {
  55. #asm
  56.     PUSH    AX
  57.     PUSH    ES
  58.     PUSH    BX
  59.     MOV        AH,2fh
  60.     INT        21h
  61.     MOV        WORD dtads_,ES
  62.     MOV        WORD dtadx_,BX
  63.     POP        BX
  64.     POP        ES
  65.     POP        AX
  66. #
  67. }
  68.  
  69. restdta()
  70. {
  71. #asm
  72.     PUSH    DS
  73.     PUSH    DX
  74.     PUSH    AX
  75.     MOV        DX,WORD dtads_
  76.     MOV        DS,DX
  77.     MOV        DX,WORD dtadx_
  78.     MOV        AH,1AH
  79.     INT        21h
  80.     POP        AX
  81.     POP        DX
  82.     POP        DS
  83. #
  84. }
  85.  
  86. char *dtap;
  87.  
  88. setdta(newdta)
  89. char *newdta;
  90. {
  91.     dtap = newdta;
  92. #asm
  93.     PUSH    DX
  94.     PUSH    AX
  95.     MOV        DX,WORD dtap_
  96.     MOV        AH,1AH
  97.     INT        21h
  98.     POP        AX
  99.     POP        DX
  100. #
  101. }
  102.  
  103. char *dirfnp;
  104. int dirret;
  105.  
  106. dirfst(s)
  107. char *s;
  108. {
  109.     dirfnp = s;
  110. #asm
  111.     PUSH    DX
  112.     PUSH    CX
  113.     MOV        DX,WORD dirfnp_
  114.     MOV        AH,4eh
  115.     INT        21h
  116.     JC        D56X1
  117.     MOV        AX,0
  118. D56X1:    NOP
  119.     MOV        WORD dirret_,AX
  120.     POP        CX
  121.     POP        DX
  122. #
  123.     return dirret;
  124. }
  125.  
  126. dirnxt()
  127. {
  128. #asm
  129.     MOV        AH,4fh
  130.     INT        21h
  131.     JC    D56X2
  132.     MOV    AX,0
  133. D56X2:    NOP
  134.     MOV        WORD dirret_,AX
  135. #
  136.     return dirret;
  137. }
  138.  
  139.  
  140. /* ================================================================ */
  141. /*
  142.     From Dr. Dobbs #108 October 1985.   */
  143.  
  144. /* fixpath() processes a DOS pathname for two different uses.
  145.     The input path, *ip, is presumably a command operand like the 
  146.     first operand of DIR.  One output, the search path *sp, is 
  147.     the input possibly augmented with "*.*" or "\*.*" so that it 
  148.     will work reliably with DOS functions 4E/$f.  The other output
  149.     is a lead-in path, *lip, which can be prefixed to the simple 
  150.     filename.ext returned by fuctions 4E/4F to make a complete path 
  151.     for opening or erasing a file.
  152.  
  153.     The function returns 1 if it is successful, but 0 if the 
  154.     input path can't be processed and should not be used.
  155.  
  156.     Some input paths can be processed here yet be invalid or 
  157.     useless.  The search path produced from such an input wwill
  158.     cause an error return from function 4E (search first match). */
  159. /* ================================================================ */
  160.  
  161. int fixpath(ip, sp, lip)
  162. register char     *ip,    /* input path */
  163.                 *sp,    /* the search path */
  164.                 *lip;    /* the lead-in or prefix path */
  165. {
  166.     char *cp;            /* work pointer for scanning paths */
  167.     int attr;            /* attribute for chgattr */
  168.     int ret, strlen(), strcpy(), strcmp(), strcat(), chgattr();
  169.  
  170. /* ================================================================ */
  171. /*    Pick off 4 special cases:
  172.     (1)    the NULL string, which we take to mean "*.*"
  173.     (2)    the simple "d:" reference to a drive, which we also take
  174.         to mean "d:*.*"
  175.     (3)    the root-dir reference "d:\" which is mishandled by 
  176.         function 0x4300 of both DOS 2.1 and 3.0.
  177.     (4)    any reference that ends in "\"
  178.  
  179.     In all cases, the input path is ok as a lead-in, but it needs
  180.     the global qualifier *.* added for searching.
  181.  
  182. /* ================================================================ */
  183.  
  184.     if ((strlen(ip) == 0)                /* null string */
  185.         || (strcmp(ip+1, ":") == 0)        /* d: only */
  186.         || (ip[strlen(ip)-1] == '\\'))    /* ends in backslash */
  187.         {
  188.             strcpy(lip, ip);            /* input is ok as prefix */
  189.             strcpy(sp, ip);
  190.             strcat(sp, "*.*");            /* add *.* for search */
  191.             return (1);
  192.         }
  193.  
  194. /* ================================================================ */
  195. /*    Ok, we have a non-null string not ending in \ and not a lone
  196.     drive letter.  Four possibilities remain:
  197.     (1)    an explicit file reference, b:\mydir\mydat
  198.     (2)    an explicit directory reference, \mydir
  199.     (3)    an ambiguous file reference, *.* or b:\mydir\*.dat
  200.     (4)    an unknown name, a:noway or b:\mydir\nonesuch.dat
  201.  
  202.     We can separate this with fair reliability using DOS function
  203.     0x4300, get attributes from path.
  204.  
  205.  
  206. /* ================================================================ */
  207.  
  208.     attr = 0x0000;                        /* output area for get command */
  209.     ret = chgattr('G', ip, &attr);        /* get attributes for this path */
  210.  
  211.     if (ret == 0x0002) 
  212.  
  213.     /*   the path is valid, in that all directories and drives
  214.         named in it are valid, but the final name is unknown.  No
  215.         files will be found in a search, so quit now.   */
  216.  
  217.         return (0);
  218.  
  219.     if ((ret == 0x0003) 
  220.         || ((ret == 0) && ((attr & 0x0010) == 0))) {
  221.  
  222.     /* Error 3, path not found, could mean total junk or a 
  223.         misspelt directory name, but most likely it just means
  224.         the path ends in an ambiguous name.  If there's an error
  225.         the initial search (function 4Eh) will fail.
  226.  
  227.         With no error and reg cx not showing the directory 
  228.         attribute flags 0010, we have a normal, unambiguous file
  229.         pathname like "b:\mydir\mydat" or just "myprog.com".
  230.  
  231.         In either case the search path is the whole input
  232.         path.  The lead-in is that shorn of whatever follows the 
  233.         rightmost \ or :, whichever comes last -- or just a null
  234.         string if there is no \ or :.        */
  235.  
  236.         strcpy(sp, ip);            /* working copy of ip in sp */
  237.         cp = sp + strlen(sp) -1;
  238.         for (; cp > sp; --cp)
  239.             if (('\\' == *cp) || (':' == *cp)) 
  240.                 break;
  241.         if (cp > sp)
  242.             ++cp;                /* retain colon or slash */
  243.         *cp = '\0';                /* make a null string */
  244.         strcpy(lip, sp);
  245.         strcpy(sp, ip);            /* whole input for search */
  246.         return (1);
  247.     }
  248.  
  249.     if ((ret == 0) && (attr & 0x0010)) {
  250.  
  251.     /* No error and the directory attribute returned in cx
  252.         shows an unambiguous path that happpens to end in the 
  253.         name of a directory, for instance "..\..\bin" or
  254.         "b:\mydir".  Applying the rules of DIR or COPY, we
  255.         have to treat these as global refs to all files named in 
  256.         the directory.  The search path is the input with 
  257.         "\*.*" tacked onto it.  The lead-in path is just the 
  258.         input plus a backslash.            */
  259.  
  260.         strcpy(sp, ip);
  261.         strcpy(lip, ip);
  262.         strcat(sp, "\\*.*");
  263.         strcat(lip, "\\");
  264.         return (1);
  265.     }
  266.  
  267.     else {
  268.         /* unexpected events make me nervous, so give up */
  269.         return (0);
  270.     }
  271. }
  272.  
  273. int rax, rcx;
  274. char *rdx;
  275.  
  276. int chgattr(getset, path, attr)
  277. char getset, *path;
  278. int *attr;
  279. {
  280.     if (getset == 'S') {
  281.         rcx = *attr;
  282.         rax = 0x4301;
  283.     }
  284.     else
  285.         rax = 0x4300;
  286.     
  287.     rdx = path;
  288.  
  289. #asm
  290.     PUSH    DX
  291.     PUSH    CX
  292.     PUSH    AX
  293.     MOV        DX,WORD rdx_
  294.     MOV        AX,WORD rax_
  295.     MOV        CX,WORD rcx_
  296.     INT        21H
  297.     MOV        WORD rax_,AX
  298.     JC        D56X9
  299.     MOV        WORD rax_,0
  300. D56X9:    NOP
  301.     MOV        WORD rcx_,CX
  302.     POP        AX
  303.     POP        CX
  304.     POP        DX
  305. #
  306.     if (rax == 0)
  307.         *attr = rcx;
  308.     return(rax);
  309. }        
  310.